package ch.so.sogis.verification.grenzlinien.liegenschaften;

import java.io.IOException;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Collection;

import ch.so.sogis.interlis.*;
import ch.interlis.iom.*;
import ch.interlis.iox.*;
import ch.interlis.iox_j.jts.Iox2jts;
import ch.interlis.iox_j.jts.Iox2jtsException;
import ch.interlis.iox_j.jts.Jts2iox;

import com.vividsolutions.jump.io.*;
import org.openjump.core.apitools.IOTools;
import com.vividsolutions.jump.feature.*;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.precision.SimpleGeometryPrecisionReducer;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.geom.prep.PreparedPoint;
import com.vividsolutions.jts.operation.union.CascadedPolygonUnion;
import com.vividsolutions.jts.operation.overlay.snap.LineStringSnapper;
import com.vividsolutions.jts.operation.polygonize.Polygonizer;
import com.vividsolutions.jump.util.CoordinateArrays;
import com.vividsolutions.jump.task.DummyTaskMonitor;
import com.vividsolutions.jts.index.SpatialIndex;
import com.vividsolutions.jts.index.strtree.STRtree;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.operation.distance.DistanceOp;
import com.vividsolutions.jts.operation.linemerge.LineMerger;


public class Liegenschaften {
	
	private FeatureDataset fd_A = null;
	private FeatureDataset fd_B = null;
	private String geomName_A = null;
	private String geomName_B = null;
	
	//private SpatialIndex idx_arcpoint_A = new STRtree();
	//private SpatialIndex idx_arcpoint_B = new STRtree();
	
	public Liegenschaften(FeatureDataset fd_A, String geomName_A, FeatureDataset fd_B, String geomName_B) {
		this.fd_A = fd_A;
		this.fd_B = fd_B;
		this.geomName_A = geomName_A;
		this.geomName_B = geomName_B;
	}
	
	public void run() {
		
		// Gemeinde A
		// Segmente einlesen und Bogenpunkte
		// indizieren.
		ArrayList segments_A = getSegments(fd_A, geomName_A);
		SpatialIndex idx_arcpoint_A = createArcPointIndex(segments_A);
		
		// Aussenpolygon/Boundary erstellen
		Polygonizer polygonizer = new Polygonizer();
		polygonizer.add(segments_A);
		ArrayList polys = (ArrayList) polygonizer.getPolygons();

		CascadedPolygonUnion union = new CascadedPolygonUnion(polys);
		Geometry geom = union.union();
		System.out.println(geom.toString());

		// Gemeinde A
		// Segmente einlesen und Bogenpunkte
		// indizieren.
		ArrayList segments_B = getSegments(fd_B, geomName_B);
		SpatialIndex idx_arcpoint_B = createArcPointIndex(segments_B);
		
		// Aussenpolygon/Boundary erstellen
		polygonizer = new Polygonizer();
		polygonizer.add(segments_B);
		polys.clear();
		polys = (ArrayList) polygonizer.getPolygons();
		
		union = new CascadedPolygonUnion(polys);
		geom = union.union();
		System.out.println(geom.toString());

	
	}
	
	private SpatialIndex createArcPointIndex(ArrayList segments) {
		SpatialIndex idx = new STRtree();
		
		for (int i=0; i<segments.size();i++) {
			LineString l = (LineString) segments.get(i);
			if(l.getNumPoints() > 2) {
				Point p = new GeometryFactory().createPoint(l.getCoordinateN(1));
				idx.insert(p.getEnvelopeInternal(), p);
				//System.out.println(p);
			}
		}
		return idx;
	}
	
	private ArrayList getSegments(FeatureDataset fd, String geomName) {
		ArrayList segments = new ArrayList();
		Iterator it = fd.iterator();
		while(it.hasNext()) {
			BasicFeature f = (BasicFeature) it.next();
			try {
				IomObject polyline = Wkt2iox.wkt2polyline((String) f.getAttribute(geomName));
				ArrayList list = Iox2wkt.polyline2segments(polyline);
				segments.addAll(list);

			} catch (ParseException pe) {
				pe.printStackTrace();
			}
		}
		return segments;
	}
	

}
